/*
lengxiangyi code
    ____            _________________
   |EC16|--A------>| P33             |         
	 |____|--B------>| P32          P54|--->(5V air pump moto)
	    |     press  |    stc8g1k08a   |
			C       |0-->| P55(EX_INT3)    |  
			|       |0   |_________________| 
		  |        | 
		 GND       |
              GND

*/

#include <stc8g.h>
#include <intrins.h>

#define MOTOR_PIN P54  // moto pwm out
#define ENCODER_A P33  // EC16 A
#define ENCODER_B P32  // EC16 B
#define EX3         0x20
#define EX3_OFF     0x00
#define POWER_OFF   0
#define POWER_ON    1

#define P3PU  (*(unsigned char volatile xdata *)0xfe13)
	
volatile int encoder_count = 50;  // 
int target_speed = 0;  
int current_speed = 0;  
int pwm_duty = 0;       // PWM duty value(0-100)
bit MASK=1,POWER_EN=1;  //MASK indicate the time-out flag, POWER_EN indicate the work/stop status
int status=POWER_OFF;

void Delay10ms(void)	//@11.0592MHz
{
	unsigned char data i, j;

	_nop_();
	_nop_();
	i = 144;
	j = 157;
	do
	{
		while (--j);
	} while (--i);
}




void Timer0_Init(void)		//2ms @11.0592MHz
{
	AUXR |= 0x80;			//1T mode
	TMOD &= 0xF0;			
	TL0 = 0x69;				
	TH0 = 0xF6;				
	TF0 = 0;				
	ET0 = 1;       
	TR0 = 1;				
}

void Timer1_Init(void)		//1ms @11.0592MHz
{
	AUXR |= 0x40;			
	TMOD &= 0x0F;			
	TL1 = 0xCD;				
	TH1 = 0xD4;				
	TF1 = 0;				
	ET1 = 1;       
	//TR1 = 1;				
	TR1 = 0;
}


void Encoder_Init(void) {
    IT1 = 1;  
    EX1 = 1;  
    EA = 1;   
}

void Timer0_ISR(void) interrupt 1 {
    static int pwm_count = 0;  
    pwm_count++;

    if (pwm_count >= 100) {  
        pwm_count = 0;
    }

    if (pwm_count < pwm_duty) {  
        MOTOR_PIN = 1&MASK&POWER_EN;  
    } else {
        MOTOR_PIN = 0&MASK&POWER_EN;  
    }
}

void Timer1_ISR(void) interrupt 3 {
	   static int time_count = 0;
	   static  time_out = 0;
	   time_count++;
	   if (time_count >= 3000) {
			 time_out++;
			 time_count=0;
		 }
		 if (time_count < 2000) {  
        MASK = 1;  
    } else {
        MASK = 0;  
    }
		if (time_out==2400){ //2400
			ET1=0;
			POWER_EN=0;
			time_out=0;
			time_count=0;
			MASK=0;
			status=POWER_OFF;
			TR1=0;
		 }
			
		 
}

void EX1_ISR(void) interrupt 2 {
	
	 if (ENCODER_B==1)  encoder_count+=5;		
	 if (ENCODER_B==0) 	encoder_count-=5;
	 if	(encoder_count>100)	encoder_count=100;
	 if (encoder_count<0)	encoder_count=0;
}

void EX3_ISR(void) interrupt 11 {
	INTCLKO = EX3_OFF;
	Delay10ms();
	if(P55==0){
	switch (status) {
		case POWER_OFF : 	POWER_EN=1;	MASK=1;	TR1=1;ET1=1; status=POWER_ON; break;
	  case POWER_ON  :  POWER_EN=0; MASK=0;	TR1=0;ET1=0; status=POWER_OFF;break;
	  default:;
	}
  }
	INTCLKO = EX3;
}

void main(void) {

	  P5M0 = (P5M0 & ~0x20) | 0x10; P5M1 &= ~0x30; 
		P3M0 &= ~0x0c; P3M1 |= 0x0c; 
  	P_SW2 |= 0x80;      //enable XFR register access function
	  P3PU |= 0x0c;       //enable up 4.7k resitor
	  INTCLKO = EX3;
    Timer0_Init();  // for pwm use
	  Timer1_Init();  // for time-out use
    Encoder_Init(); 
    MOTOR_PIN = 0;  
    status=POWER_OFF;
	  POWER_EN=0; MASK=0;	
    while (1) {      
        target_speed = encoder_count;       
        if (current_speed < target_speed) 
            current_speed++;
         else if (current_speed > target_speed) 
            current_speed--;
        
        
        pwm_duty = current_speed;

        
        if (pwm_duty > 100) 
            pwm_duty = 100;
         else if (pwm_duty < 0) 
            pwm_duty = 0;
        
    }
}